WOLF core
WOLF: A Modular Estimation Framework for Robotics
XXXXXXXXXXXXXXXXXXXXXXXXvoid(0)" frameborder="0" name="MSearchResults" id="MSearchResults">
logging.h
Go to the documentation of this file.
1// WOLF - Copyright (C) 2020-2026
2// Institut de Robòtica i Informàtica Industrial, CSIC-UPC.
3// Authors: Joan Solà Ortega (jsola@iri.upc.edu) and
4// Joan Vallvé Navarro (jvallve@iri.upc.edu)
5// All rights reserved.
6//
7// This file is part of WOLF: http://www.iri.upc.edu/wolf
8// WOLF is free software: you can redistribute it and/or modify
9// it under the terms of the GNU General Public License version 3
10// as published by the Free Software Foundation.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this program. If not, see <http://www.gnu.org/licenses/>.
19#pragma once
20
21// third_party include
22#include <map>
23#if __has_include(<boost/assert/source_location.hpp>)
24#include <boost/assert/source_location.hpp>
25#endif
26
27// spdlog include
28#include "spdlog/spdlog.h"
29#include "spdlog/async.h"
30#include "spdlog/sinks/stdout_color_sinks.h"
31
32// enable the use of ostream operator<<
33#include "spdlog/fmt/ostr.h"
34
35// Wolf includes
37
38namespace wolf
39{
40namespace internal
41{
42namespace do_not_enter_where_the_wolf_lives
43{
44#define __INTERNAL_WOLF_MAIN_LOGGER_NAME_ "wolf_main_console"
45
46static constexpr auto repeated_brace = std::make_tuple(
47 "{}",
48 "{}{}",
49 "{}{}{}",
50 "{}{}{}{}",
51 "{}{}{}{}{}",
52 "{}{}{}{}{}{}",
53 "{}{}{}{}{}{}{}",
54 "{}{}{}{}{}{}{}{}",
55 "{}{}{}{}{}{}{}{}{}",
56 "{}{}{}{}{}{}{}{}{}{}",
57 "{}{}{}{}{}{}{}{}{}{}{}",
58 "{}{}{}{}{}{}{}{}{}{}{}{}",
59 "{}{}{}{}{}{}{}{}{}{}{}{}{}",
60 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
61 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
62 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
63 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
64 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
65 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
66 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
67 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
68 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
69 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
70 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
71 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
72 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
73 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
74 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
75 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
76 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
77 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
78 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
79 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
80 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
81 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
82 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
83 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
84 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
85 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
86 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
87 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
88 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
89 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
90 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
91 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
92 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
93 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
94 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
95 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
96 "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}"); // up to
97 // 50
98 // args.
99 // should
100 // be
101 // enough
103{
104 public:
105 Logger(const std::string& name);
106
107 Logger(std::string&& name);
108
109 ~Logger();
110
111 // Not copyable/movable
112 Logger(Logger&) = delete;
113 void operator=(Logger&) = delete;
114 Logger(Logger&&) = delete;
115 void operator=(Logger&&) = delete;
116
117 template <typename... Args>
118 void info(Args&&... args) const;
119
120 template <typename... Args>
121 void warn(Args&&... args) const;
122
123 template <typename... Args>
124 void error(Args&&... args) const;
125
126 template <typename... Args>
127 void debug(Args&&... args) const;
128
129 template <typename... Args>
130 void trace(Args&&... args) const;
131
132 bool set_async_queue(const std::size_t q_size);
133
134 void set_pattern(const std::string& p);
135
136 protected:
137 const std::string log_name_;
138
139 std::shared_ptr<spdlog::logger> console_;
140};
141
142inline Logger::Logger(const std::string& name) : log_name_(name)
143{
144 // Create main logger
145 console_ = spdlog::stdout_color_mt(log_name_);
146
147#ifdef _WOLF_TRACE
148 console_->set_level(spdlog::level::trace);
149#endif
150
151 // Enable asynchronous logging
152 // Queue size must be a power of 2
153 spdlog::init_thread_pool(4096, 1);
154
156 // [thread num][hour:minutes:seconds.nanoseconds][log type] #log-content
157 // set_pattern("[%t][%H:%M:%S.%F][%l] %v");
158
159 // [log type][MM/DD/YY - hour:minutes:seconds.nanoseconds] #log-content
160 // set_pattern("[%l][%x - %H:%M:%S.%F] %v");
161
162 // [log type][hour:minutes:seconds] #log-content
163 // set_pattern("%^[%l][%H:%M:%S] %v%$");
164
165 // [log type]#log-content
166 set_pattern("%^[%l]%v%$");
167 else
168 // [logger name][thread num][hour:minutes:seconds.nanoseconds][log type] #log-content
169 // set_pattern("[" + log_name_ + "]" +"[%t][%H:%M:%S.%F][%l] %v");
170
171 // [log type][MM/DD/YY - hour:minutes:seconds.nanoseconds][logger name] #log-content
172 set_pattern("%^[%l][%x - %H:%M:%S.%F][" + log_name_ + "] %v%$");
173}
174
175inline Logger::Logger(std::string&& name) : log_name_(std::forward<std::string>(name))
176{
177 // Create main logger
178 console_ = spdlog::stdout_color_mt(log_name_);
179
180#ifdef _WOLF_TRACE
181 console_->set_level(spdlog::level::trace);
182#endif
183
184 // Enable asynchronous logging
185 // Queue size must be a power of 2
186 spdlog::init_thread_pool(4096, 1);
187
189 // [thread num][hour:minutes:seconds.nanoseconds][log type] #log-content
190 // set_pattern("[%t][%H:%M:%S.%F][%l] %v");
191
192 // [log type][MM/DD/YY - hour:minutes:seconds.nanoseconds] #log-content
193 // set_pattern("[%l][%x - %H:%M:%S.%F] %v");
194
195 // [log type][hour:minutes:seconds] #log-content
196 // set_pattern("%^[%l][%H:%M:%S] %v%$");
197
198 // [log type][source_file line][function] #log-content
199 set_pattern("%^[%l]%v%$");
200 else
201 // [logger name][thread num][hour:minutes:seconds.nanoseconds][log type] #log-content
202 // set_pattern("[" + log_name_ + "]" +"[%t][%H:%M:%S.%F][%l] %v");
203
204 // [log type][MM/DD/YY - hour:minutes:seconds.nanoseconds][logger name] #log-content
205 set_pattern("%^[%l][%x - %H:%M:%S.%F][" + log_name_ + "] %v%$");
206}
207
209{
210 spdlog::drop(log_name_);
211}
212
213template <typename... Args>
214void Logger::info(Args&&... args) const
215{
216#if FMT_VERSION >= 90000 // from v9.0 FMT does not takes ostream formatter
217 console_->info(std::get<sizeof...(args) - 1>(repeated_brace), fmt::streamed(std::forward<Args>(args))...);
218#else
219 console_->info(std::get<sizeof...(args) - 1>(repeated_brace), std::forward<Args>(args)...);
220#endif
221}
222
223template <typename... Args>
224void Logger::warn(Args&&... args) const
225{
226#if FMT_VERSION >= 90000 // from v9.0 FMT does not takes ostream formatter
227 console_->warn(std::get<sizeof...(args) - 1>(repeated_brace), fmt::streamed(std::forward<Args>(args))...);
228#else
229 console_->warn(std::get<sizeof...(args) - 1>(repeated_brace), std::forward<Args>(args)...);
230#endif
231}
232
233template <typename... Args>
234void Logger::error(Args&&... args) const
235{
236#if FMT_VERSION >= 90000 // from v9.0 FMT does not takes ostream formatter
237 console_->error(std::get<sizeof...(args) - 1>(repeated_brace), fmt::streamed(std::forward<Args>(args))...);
238#else
239 console_->error(std::get<sizeof...(args) - 1>(repeated_brace), std::forward<Args>(args)...);
240#endif
241}
242
243template <typename... Args>
244void Logger::debug(Args&&... args) const
245{
246#if FMT_VERSION >= 90000 // from v9.0 FMT does not takes ostream formatter
247 console_->debug(std::get<sizeof...(args) - 1>(repeated_brace), fmt::streamed(std::forward<Args>(args))...);
248#else
249 console_->debug(std::get<sizeof...(args) - 1>(repeated_brace), std::forward<Args>(args)...);
250#endif
251}
252
253template <typename... Args>
254void Logger::trace(Args&&... args) const
255{
256#if FMT_VERSION >= 90000 // from v9.0 FMT does not takes ostream formatter
257 console_->trace(std::get<sizeof...(args) - 1>(repeated_brace), fmt::streamed(std::forward<Args>(args))...);
258#else
259 console_->trace(std::get<sizeof...(args) - 1>(repeated_brace), std::forward<Args>(args)...);
260#endif
261}
262
263inline bool Logger::set_async_queue(const std::size_t q_size)
264{
265 bool p2 = q_size % 2 == 0;
266
267 if (p2) spdlog::init_thread_pool(q_size, 1);
268
269 return q_size;
270}
271
272inline void Logger::set_pattern(const std::string& p)
273{
274 console_->set_pattern(p);
275}
276
277using LoggerPtr = std::unique_ptr<Logger>;
278
280{
281 public:
282 LoggerManager() = default;
283 ~LoggerManager() = default;
284
285 bool exists(const std::string& name) const
286 {
287 std::lock_guard<std::mutex> lock(mut_);
288 return existsImpl(name);
289 }
290
291 const Logger& getLogger(const std::string& name) /*const*/
292 {
293 std::lock_guard<std::mutex> lock(mut_);
294
295 if (!existsImpl(name)) addLogger(name);
296
297 return *(logger_map_.at(name));
298 }
299
300 protected:
301 mutable std::mutex mut_;
302
303 std::map<const std::string, const LoggerPtr> logger_map_;
304
305 bool addLogger(const std::string& name)
306 {
308 const bool created =
309 existsImpl(name) ? false : logger_map_.emplace(name, std::make_unique<Logger>(name)).second;
310 return created;
311 }
312
313 bool existsImpl(const std::string& name) const
314 {
315 return (logger_map_.find(name) != logger_map_.end());
316 }
317};
318
319} /* namespace do_not_enter_where_the_wolf_lives */
320
323
324} /* namespace internal */
325} /* namespace wolf */
326
327#define WOLF_STRINGIFY(x) #x
328#define WOLF_STR_HELPER(x) WOLF_STRINGIFY(x)
329
330/* Logging macros
331 *
332 * WOLF_DEBUG, WOLF_TRACE (and their _COND and _NAMED versions) only print if _WOLF_DEBUG / _WOLF_TRACE are defined.
333 * Otherwise, they expand to an empty statement. To behave the same in all builds, they are wrapped in
334 * 'do { ... } while (0)', so that:
335 * - they are a single statement, safe as the body of an if/else without braces:
336 * if (a) WOLF_DEBUG("..."); else foo();
337 * - the ';' after them is mandatory (a missing ';' is a compile error in all builds). With an empty expansion, a
338 * missing ';' would make the next statement the body of a preceding 'if' only in release builds:
339 * if (a) WOLF_DEBUG("...") // missing ';'
340 * foo(); // RELEASE: if (a) foo();
341 */
342
344
345#define WOLF_ASYNC_QUEUE_LOG_NAMED(name, ...) \
346 wolf::internal::WolfLoggerManager::get().getLogger(name).set_async_queue(x);
347
348#define WOLF_INFO_NAMED(name, ...) \
349 { \
350 char this_file[] = __FILE__; \
351 wolf::internal::WolfLoggerManager::get().getLogger(name).info( \
352 "[", basename(this_file), " L", __LINE__, "] ", __FUNCTION__, ": ", __VA_ARGS__); \
353 }
354#define WOLF_INFO_NAMED_COND(name, cond, ...) \
355 if (cond) WOLF_INFO_NAMED(name, __VA_ARGS__);
356
357#define WOLF_WARN_NAMED(name, ...) \
358 { \
359 char this_file[] = __FILE__; \
360 wolf::internal::WolfLoggerManager::get().getLogger(name).warn( \
361 "[", basename(this_file), " L", __LINE__, "] ", __FUNCTION__, ": ", __VA_ARGS__); \
362 }
363#define WOLF_WARN_NAMED_COND(name, cond, ...) \
364 if (cond) WOLF_WARN_NAMED(name, __VA_ARGS__);
365
366#define WOLF_ERROR_NAMED(name, ...) \
367 { \
368 char this_file[] = __FILE__; \
369 wolf::internal::WolfLoggerManager::get().getLogger(name).error( \
370 "[", basename(this_file), " L", __LINE__, "] ", __FUNCTION__, ": ", __VA_ARGS__); \
371 }
372#define WOLF_ERROR_NAMED_COND(name, cond, ...) \
373 if (cond) WOLF_ERROR_NAMED(name, __VA_ARGS__);
374
375#ifdef _WOLF_DEBUG
376#define WOLF_DEBUG_NAMED(name, ...) \
377 do \
378 { \
379 char this_file[] = __FILE__; \
380 wolf::internal::WolfLoggerManager::get().getLogger(name).debug( \
381 "[", basename(this_file), " L", __LINE__, "] ", __FUNCTION__, ": ", __VA_ARGS__); \
382 } while (0)
383#define WOLF_DEBUG_NAMED_COND(name, cond, ...) \
384 do \
385 { \
386 if (cond) WOLF_DEBUG_NAMED(name, __VA_ARGS__); \
387 } while (0)
388#else
389#define WOLF_DEBUG_NAMED(name, ...) \
390 do \
391 { \
392 } while (0)
393#define WOLF_DEBUG_NAMED_COND(name, cond, ...) \
394 do \
395 { \
396 } while (0)
397#endif
398
399#ifdef _WOLF_TRACE
400#define WOLF_TRACE_NAMED(name, ...) \
401 do \
402 { \
403 char this_file[] = __FILE__; \
404 wolf::internal::WolfLoggerManager::get().getLogger(name).trace( \
405 "[", basename(this_file), " L", __LINE__, "] ", __FUNCTION__, ": ", __VA_ARGS__); \
406 } while (0)
407#define WOLF_TRACE_NAMED_COND(name, cond, ...) \
408 do \
409 { \
410 if (cond) WOLF_TRACE_NAMED(name, __VA_ARGS__); \
411 } while (0)
412#else
413#define WOLF_TRACE_NAMED(name, ...) \
414 do \
415 { \
416 } while (0)
417#define WOLF_TRACE_NAMED_COND(name, cond, ...) \
418 do \
419 { \
420 } while (0)
421#endif
422
424
425#define WOLF_ASYNC_QUEUE_LOG(x) wolf::internal::WolfLogger::get(__INTERNAL_WOLF_MAIN_LOGGER_NAME_).set_async_queue(x);
426
427#define WOLF_INFO(...) \
428 { \
429 char this_file[] = __FILE__; \
430 wolf::internal::WolfLogger::get(__INTERNAL_WOLF_MAIN_LOGGER_NAME_) \
431 .info("[", basename(this_file), " L", __LINE__, "] ", __FUNCTION__, ": ", __VA_ARGS__); \
432 }
433#define WOLF_INFO_COND(cond, ...) \
434 if (cond) WOLF_INFO(__VA_ARGS__);
435
436#define WOLF_WARN(...) \
437 { \
438 char this_file[] = __FILE__; \
439 wolf::internal::WolfLogger::get(__INTERNAL_WOLF_MAIN_LOGGER_NAME_) \
440 .warn("[", basename(this_file), " L", __LINE__, "] ", __FUNCTION__, ": ", __VA_ARGS__); \
441 }
442#define WOLF_WARN_COND(cond, ...) \
443 if (cond) WOLF_WARN(__VA_ARGS__);
444
445#define WOLF_ERROR(...) \
446 { \
447 char this_file[] = __FILE__; \
448 wolf::internal::WolfLogger::get(__INTERNAL_WOLF_MAIN_LOGGER_NAME_) \
449 .error("[", basename(this_file), " L", __LINE__, "] ", __FUNCTION__, ": ", __VA_ARGS__); \
450 }
451#define WOLF_ERROR_COND(cond, ...) \
452 if (cond) WOLF_ERROR(__VA_ARGS__);
453
454#ifdef _WOLF_DEBUG
455#define WOLF_DEBUG(...) \
456 do \
457 { \
458 char this_file[] = __FILE__; \
459 wolf::internal::WolfLogger::get(__INTERNAL_WOLF_MAIN_LOGGER_NAME_) \
460 .debug("[", basename(this_file), " L", __LINE__, "] ", __FUNCTION__, ": ", __VA_ARGS__); \
461 } while (0)
462#define WOLF_DEBUG_COND(cond, ...) \
463 do \
464 { \
465 if (cond) WOLF_DEBUG(__VA_ARGS__); \
466 } while (0)
467#else
468#define WOLF_DEBUG(...) \
469 do \
470 { \
471 } while (0)
472#define WOLF_DEBUG_COND(cond, ...) \
473 do \
474 { \
475 } while (0)
476#endif
477
478#ifdef _WOLF_TRACE
479#define WOLF_TRACE(...) \
480 do \
481 { \
482 char this_file[] = __FILE__; \
483 wolf::internal::WolfLogger::get(__INTERNAL_WOLF_MAIN_LOGGER_NAME_) \
484 .trace("[", basename(this_file), " L", __LINE__, "] ", __FUNCTION__, ": ", __VA_ARGS__); \
485 } while (0)
486#define WOLF_TRACE_COND(cond, ...) \
487 do \
488 { \
489 if (cond) WOLF_TRACE(__VA_ARGS__); \
490 } while (0)
491#else
492#define WOLF_TRACE(...) \
493 do \
494 { \
495 } while (0)
496#define WOLF_TRACE_COND(cond, ...) \
497 do \
498 { \
499 } while (0)
500#endif
501
502#ifdef _WOLF_DEBUG // DEBUG: WOLF_PROC_DEBUG = WOLF_DEBUG
503#define WOLF_PROC_DEBUG(...) WOLF_DEBUG(__VA_ARGS__)
504#else // RELEASE & source_location.hpp (boost >= 1.73): print depending on debug_verbose_level_
505#if __has_include(<boost/assert/source_location.hpp>)
506#define WOLF_PROC_DEBUG(...) \
507 { \
508 static_assert(std::is_base_of<ProcessorBase, typename std::remove_pointer<decltype(this)>::type>::value, \
509 "WOLF_PROC_DEBUG can only be used in processors"); \
510 /* Check if the caller's function name contains 'getType()' */ \
511 bool called_from_derived = std::string(boost::source_location(BOOST_CURRENT_LOCATION).function_name()) \
512 .rfind("wolf::" + getType() + "::") == 0; \
513 /* Check if the message should be printed according to debug_verbose_level_ */ \
514 if (debug_verbose_level_ == "all" or (called_from_derived and (debug_verbose_level_ == "derived")) or \
515 (not called_from_derived and (debug_verbose_level_ == "base"))) \
516 { \
517 /* Print as WOLF_DEBUG even if WOLF_DEBUG is disabled (copied from logging.h) */ \
518 char this_file[] = __FILE__; \
519 wolf::internal::WolfLogger::get(__INTERNAL_WOLF_MAIN_LOGGER_NAME_) \
520 .debug("[", basename(this_file), " L", __LINE__, "] ", __FUNCTION__, ": ", __VA_ARGS__); \
521 } \
522 }
523#else // RELEASE & no source_location.hpp (no boost or < 1.73) --> printing if debug_verbose_level_ != "none"
524#define WOLF_PROC_DEBUG(...) \
525 { \
526 static_assert(std::is_base_of<ProcessorBase, typename std::remove_pointer<decltype(this)>::type>::value, \
527 "WOLF_PROC_DEBUG can only be used in processors"); \
528 /* message will be printed if debug_verbose_level_ != "none" */ \
529 if (debug_verbose_level_ != "none") \
530 { /* Print as WOLF_DEBUG even if WOLF_DEBUG is disabled (copied from logging.h) */ \
531 char this_file[] = __FILE__; \
532 wolf::internal::WolfLogger::get(__INTERNAL_WOLF_MAIN_LOGGER_NAME_) \
533 .debug("[", basename(this_file), " L", __LINE__, "] ", __FUNCTION__, ": ", __VA_ARGS__); \
534 } \
535 }
536#endif
537#endif
538
539#define WOLF_PROC_DEBUG_COND(cond, ...) \
540 if (cond) WOLF_PROC_DEBUG(__VA_ARGS__);
A thread-safer (?) Singleton implementation with argument forwarding.
Definition: singleton.h:33
bool exists(const std::string &name) const
Definition: logging.h:285
const Logger & getLogger(const std::string &name)
Definition: logging.h:291
bool addLogger(const std::string &name)
Definition: logging.h:305
std::map< const std::string, const LoggerPtr > logger_map_
Definition: logging.h:303
bool existsImpl(const std::string &name) const
Definition: logging.h:313
void error(Args &&... args) const
Definition: logging.h:234
void info(Args &&... args) const
Definition: logging.h:214
Logger(const std::string &name)
Definition: logging.h:142
void set_pattern(const std::string &p)
Definition: logging.h:272
void debug(Args &&... args) const
Definition: logging.h:244
bool set_async_queue(const std::size_t q_size)
Definition: logging.h:263
const std::string log_name_
Definition: logging.h:137
void trace(Args &&... args) const
Definition: logging.h:254
void warn(Args &&... args) const
Definition: logging.h:224
std::shared_ptr< spdlog::logger > console_
Definition: logging.h:139
#define __INTERNAL_WOLF_MAIN_LOGGER_NAME_
Definition: logging.h:44
Definition: jet.h:1355
static constexpr auto repeated_brace
Definition: logging.h:46
std::unique_ptr< Logger > LoggerPtr
Definition: logging.h:277
Definition: capture_base.h:23